MoRGaNA / Travian Report Processor [MoRGaNA]

// ==UserScript==
// @name          Travian Report Processor [MoRGaNA]
// @namespace     travReproc
// @version 	  5.5.3
// @description   Processes Travian Reports -- Mani
// @include 	  http://*.travian*.*/*.php*
// @include 	  http://*.travian*.*/*.php*
// @exclude 	  http://*.travian*.*/hilfe.php*
// @exclude	  	  http://*.travian*.*/log*.php*
// @exclude 	  http://*.travian*.*/index.php*
// @exclude 	  http://*.travian*.*/anleitung.php*
// @exclude 	  http://*.travian*.*/impressum.php*
// @exclude 	  http://*.travian*.*/anmelden.php*
// @exclude 	  http://*.travian*.*/gutscheine.php*
// @exclude 	  http://*.travian*.*/spielregeln.php*
// @exclude 	  http://*.travian*.*/links.php*
// @exclude 	  http://*.travian*.*/geschichte.php*
// @exclude 	  http://*.travian*.*/tutorial.php*
// @exclude 	  http://*.travian*.*/manual.php*
// @exclude 	  http://*.travian*.*/manual.php*
// @exclude 	  http://*.travian*.*/ajax.php*
// @exclude 	  http://*.travian*.*/ad/*
// @exclude 	  http://*.travian*.*/chat/*
// @exclude 	  http://forum.travian*.*
// @exclude 	  http://board.travian*.*
// @exclude 	  http://shop.travian*.*
// @exclude 	  http://*.travian*.*/activate.php*
// @exclude 	  http://*.travian*.*/support.php*
// @exclude  	  http://help.travian*.*
// @exclude 	  *.css
// @exclude 	  *.js
// ==/UserScript==


/*
*Copyright © Kirne, 2010
*/
var scriptVersion = '5.5.3';  // once here and once up in the comments
var crtPage;
var queryStringValuePairs = new Array();
var ReportProcessorData;
var activeVillage;
var villages = new Array();
var debugAlerts = false;

var minTroop = 12;
var defaultTroopType = 1;
var defaultTroopNumber = 12;

var isSpeedServer = false;

var raceImageNumber = '1'; // ''=romans, '1'=teutons, '2'=gauls

var farmSettingsDialogElement;
var importExportDialogElement;
var senderSetupDialogElement;

// google chrome support
var isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
// end chrome support





function functionMain(e) {
	var crtPath = window.location.href;	
	crtPage = crtPath.substring(crtPath.substring(12).indexOf('/') + 13);
	var crtShortPage = crtPage.substring(0, crtPage.indexOf('.'));
	
	if(crtPage.indexOf('?') > -1) {
		queryStringValuePairs = ParseQueryString(crtPage.substring(crtPage.indexOf('?')+1));
	}
	
	isSpeedServer = (crtPage.indexOf("speed") != -1 || crtPage.indexOf("vip") != -1 || crtPage.indexOf("research")!= -1)
	
	//if(xpathToFirstFound("//a", document.getElementById("mtop")).title.indexOf('TB3') > -1) {
	//	BeyondActivated = true;
	//}
		
	AddStyles();
	
	LoadReportProcData();
	
	raceImageNumber = ReportProcessorData.race;
	if(raceImageNumber=='0') {
		raceImageNumber = '';
	}
	
	// legacy check
	if(ReportProcessorData.farms.length>0 && ReportProcessorData.farms[0].autoAdjustEnabled == null) {
		AmendFarmList();
	}
	if(ReportProcessorData.minRaiders == null) {
		ReportProcessorData.minRaiders = 12;
		ReportProcessorData.incRatio = 50;
		ReportProcessorData.decRatio = 20;
		SaveReportProcData();
	}
	if(ReportProcessorData.lossAlertPercentage == null) {
		ReportProcessorData.lossAlertPercentage = 50;
		SaveReportProcData();
	}
	
	LoadVillageList();
	RenderPageElements();
	
	switch(crtShortPage)
	{
		case 'dorf1':
			TrackETAs();
			break;
	    case 'berichte':
			if(crtPage.indexOf("?id=") > -1 || crtPage.indexOf("&id=") > -1) {
				if( ReportProcessorData.activated ) {
					HandleSingleReport(null);
				}
				else {
					RenderProcessReportLink();
				}
			}
			else {
				if( ReportProcessorData.activated) {
					ProcessReportList();
				}
			}
	        break;
	    case 'a2b':
			if(GetQueryStringValue('z')) {
				HandleAttackPage();
			}
			else {
				SendAttack();
			}
			break;
	    case 'karte':
			if(crtPage.indexOf("?d=") > -1) {
				UpdateFarmDataFromKartePage();
				RenderAddAsFarmLink();
			}
			break;
		case 'build':  // rally point
			if(GetQueryStringValue('gid') == '16' && (ReportProcessorData.activated || ReportProcessorData.returnToReports)) {
				ReportProcessorData.returnToReports = false;
				SaveReportProcData();
				document.location.href = 'berichte.php?t=3';
			}
			break;
		case 'spieler':
			RenderFakeLinks();
			break;
	}
}



/* ===================================== RENDERING ======================================= */


function AddStyles() {
    var css = " .rptPrcTbl {border-collapse: collapse;}";
	css += ".rptPrcTbl,.rptPrcTbl td,.rptPrcTbl th{border: 1px solid #666;padding: 0 4px !important;font-size: 10px; text-align:left!important;}\r\n";
	css += ".rptPrcTbl th{background-color: #eee;}\r\n";
	css += "#reportsTbl {margin:20px 0 0 0;}\r\n";
	css += "#farmsTbl {margin:10px 0 40px 0;}\r\n";
	css += ".scriptUpdateLink {margin: 0 10px;}\r\n";
	css += ".aSettings {float: none; clear: both; margin: 5px 0 0 0; display: block;}\r\n";
	css += ".currentReport td {background-color: green; color: #fff; font-weight: bold;}\r\n";
	css += ".rptPrcDialog {background-color: #C5DEA4; position:absolute; top: -40px; left: -550px; z-index: 20000; padding: 40px; border: 4px solid #666;}\r\n";
	css += ".rptPrcDialog button {float:right; margin: 0 0 20px 0;}\r\n";
	css += "#farmSettingsHelp {width: 570px;}\r\n";
	css += ".trptprc_resendContainer, .trptprc_fakesContainer {border: 1px solid #c0c0c0; background-color: #f3f3f3; padding:3px; font-size: 90%;}\r\n";
	css += ".trptprc_resendContainer a{margin:0 20px}\r\n";
	css += "#rptPrcFarmSettings input {width: 30px;}\r\n";
	css += ".trptprc_fakesContainer .radioContainer {width: 490px; margin-bottom: 10px;}\r\n";
	css += ".trptprc_fakesContainer input {margin-right: 25px;}\r\n";
	css += "#importExportDialogElement {background-color: #C5DEA4; position:absolute; top: -40px; left: -550px; z-index: 25000; padding: 40px; border: 4px solid #666;}\r\n";
	css += "#importExportDialogElement textarea {width:500px; height:500px; border: 1px solid #666;}";
	css += ".rptOptTbl {border-collapse: collapse;border: 1px solid #c0c0c0; margin: 20px 0 0 0;}";
	css += ".rptOptTbl th { border: 1px solid #c0c0c0; font-size: 80%; }";
	css += ".rptOptTbl td { border: 1px solid #c0c0c0; font-size: 80%;}";
	css += ".lastRow {text-align:center; background-color: #f3f3f3;}";
	css += ".lastRow p {margin: 0;}";
	css += "\r\n.radical {background-color: #80C907;}";
	css += "\r\n.super {background-color: #9ECD67;}";
	css += "\r\n.better {background-color: #CAE4AA;}";
	css += "\r\n.worse {background-color: #D55C14;}";
	css += "\r\n.worst {background-color: #db0000;}";
	css += "\r\n.same {color: #666;}";
	css += "\r\n.activeVillageTd {color: #000; font-weight:bold;}";
	css += "\r\n.eta {color: red; width: 50px;}";
	
	
	GM_addStyle(css);
}

function RenderPageElements() {
	var lastDiv = document.getElementById('side_info');
	
	var b = document.createElement("b");
	b.appendChild(document.createTextNode('Report Processor'));
	b.addEventListener("click", function(){document.location.href='http://userscripts.org/scripts/show/65944';}, true);
	insertAfter(lastDiv.lastChild, b);
	
	var aUpd = document.createElement("a");
	aUpd.href = 'javascript: ;';
	aUpd.className = 'scriptUpdateLink';
	aUpd.appendChild(document.createTextNode(scriptVersion));
	aUpd.addEventListener("click", AutoUpdate, true);
	insertAfter(lastDiv.lastChild, aUpd);
	
	if(ReportProcessorData.activated) {
		
		var btn = document.createElement("button");
		btn.textContent = "Stop Processing";
		btn.addEventListener("click", StopProcess, true);
		insertAfter(lastDiv.lastChild, btn);
		
		//insertAfter(lastDiv.lastChild, document.createTextNode("working..."));
	}
	else
	{
		var btn = document.createElement("button");
		btn.textContent = "Start Processing";
		btn.addEventListener("click", StartProcessing, true);
		insertAfter(lastDiv.lastChild, btn); 
	}
		
	var aSettings = document.createElement("a");
	aSettings.href = 'javascript: ;';
	aSettings.className = 'aSettings';
	aSettings.appendChild(document.createTextNode('Show farm settings'));
	aSettings.addEventListener("click", ShowFarmSettings, true);
	insertAfter(lastDiv.lastChild, aSettings);
	
	RenderReportsTable();
}

function ShowFarmSettings() {
	var table = CreateTable('rptPrcTbl','farmsTbl');
	
	AddTableHeaderTextCell(table, 'Village');
	AddTableHeaderTextCell(table, 'Owner');
	AddTableHeaderTextCell(table, 'Troop');
	AddTableHeaderTextCell(table, 'No.');
	AddTableHeaderTextCell(table, 'Auto adjust');
	AddTableHeaderTextCell(table, 'Raid');
	//AddTableHeaderTextCell(table, 'From');
	AddTableHeaderTextCell(table, 'Runs');	
	AddTableHeaderTextCell(table, 'Avg. Bounty');
	
	var tBody = table.tBodies[0];
	
	var farmList = ReportProcessorData.farms;
	
	for(var i=0; i<farmList.length; i++) {
		var row = document.createElement('tr');
		tBody.appendChild(row);
		
		// target village link
		var td = document.createElement('td');
		td.appendChild(CreateLink(farmList[i].villageLink, farmList[i].villageName));
		row.appendChild(td);
		
		// target player link
		var td = document.createElement('td');
		td.appendChild(CreateLink('spieler.php?uid=' + farmList[i].playerId, farmList[i].playerName));
		row.appendChild(td);
		
		// troop type image		
		var td = document.createElement('td');
		var img = document.createElement('img')
		img.src = "img/x.gif";
		img.className = 'unit u' + raceImageNumber + farmList[i].troopType;
		td.appendChild(img);
		row.appendChild(td);
		
		// troop number
		row.appendChild(CreateTableCell(farmList[i].troopNumber));
			
		// Auto adjust
		var td = document.createElement('td');		
		var checkbox = document.createElement('input');
		checkbox.type = "checkbox";
		checkbox.name = "farmAutoAdjust_"+i;
		checkbox.value = farmList[i].villageId;
		checkbox.id = "farmAutoAdjust_"+i;
		checkbox.checked = farmList[i].autoAdjustEnabled;
		checkbox.addEventListener("change", ToggleAutoAdjust, true);
		td.appendChild(checkbox);
		row.appendChild(td);
		
		// Attack type
		var td = document.createElement('td');		
		var checkbox = document.createElement('input');
		checkbox.type = "checkbox";
		checkbox.name = "farmAttackType_"+i;
		checkbox.value = farmList[i].villageId;
		checkbox.id = "farmAttackType_"+i;
		checkbox.checked = farmList[i].attackType == 2 || farmList[i].attackType == null;
		checkbox.addEventListener("change", ToggleAttackType, true);
		td.appendChild(checkbox);
		row.appendChild(td);
		
		// the rest of the stuff
		//row.appendChild(CreateTableCell(ResolveVillageName(farmList[i].senderVillageId)));
		row.appendChild(CreateTableCell(farmList[i].attackedCount));
		row.appendChild(CreateTableCell(farmList[i].averageBounty));
	}
	
	// a container
	farmSettingsDialogElement = document.createElement('div');
	farmSettingsDialogElement.id = "rptPrcFarmSettings";
	farmSettingsDialogElement.className = "rptPrcDialog";
	
	// close button
	var btn = document.createElement("button");
	btn.textContent = "Close";
	btn.addEventListener("click", HideFarmSettings, true);
	farmSettingsDialogElement.appendChild(btn);
	
	// add some text
	farmSettingsDialogElement.appendChild(GetFarmHelpText());
	
	// the race selector
	var select = document.createElement('select');
	select.name = "playerRace_"+i;
	select.id = "playerRace_"+i;
	select.setAttribute("valueName", "race");
	select.options[0] = new Option('Romans', '', (ReportProcessorData.race==''));
	select.options[1] = new Option('Teutons', '1', (ReportProcessorData.race=='1'));
	select.options[2] = new Option('Gauls', '2', (ReportProcessorData.race=='2'));
	select.addEventListener("change", SaveSettings, true);
	
	var raceSelectorContainer = document.createElement('div');
	raceSelectorContainer.appendChild(document.createTextNode('Your race: '));
	raceSelectorContainer.appendChild(select);
	
	// some settings
	var min = CreateInput("minRaiders_"+i, ReportProcessorData.minRaiders, 'Minimum raiders', 'blur', SaveSettings, 'minRaiders');
	var inc = CreateInput("incRatio_"+i, ReportProcessorData.incRatio, 'Increase ratio (%)', 'blur', SaveSettings, 'incRatio');
	var dec = CreateInput("decRatio_"+i, ReportProcessorData.decRatio, 'Decrease ratio (%)', 'blur', SaveSettings, 'decRatio');	
	var loss = CreateInput("alertLevel_"+i, ReportProcessorData.lossAlertPercentage, 'Loss alert level (%)', 'blur', SaveSettings, 'lossAlertPercentage');	
	var delay = CreateInput("delay_"+i, ReportProcessorData.delay, 'Delay (seconds)', 'blur', SaveSettings, 'delay');	
	
	farmSettingsDialogElement.appendChild(raceSelectorContainer);
	farmSettingsDialogElement.appendChild(min);
	farmSettingsDialogElement.appendChild(inc);
	farmSettingsDialogElement.appendChild(dec);
	farmSettingsDialogElement.appendChild(loss);
	farmSettingsDialogElement.appendChild(delay);
	
	// add the table
	farmSettingsDialogElement.appendChild(table); 
	
	//export and import
	var btnExp = document.createElement("button");
	btnExp.textContent = "Export farm list";
	btnExp.addEventListener("click", ShowExportDialog, true);
	farmSettingsDialogElement.appendChild(btnExp);
	
	var btnExp = document.createElement("button");
	btnExp.textContent = "Import farm list";
	btnExp.addEventListener("click", ShowImportDialog, true);
	farmSettingsDialogElement.appendChild(btnExp);
	
	// clear farm settings
	var btnClear = document.createElement("button");
	btnClear.textContent = "Remove all farms";
	btnClear.addEventListener("click", ClearData, true);
	farmSettingsDialogElement.appendChild(btnClear);
	
	insertAfter(document.getElementById('side_info').lastChild, farmSettingsDialogElement);
}

function HideFarmSettings() {
	if (farmSettingsDialogElement) {
		farmSettingsDialogElement.parentNode.removeChild(farmSettingsDialogElement);
	}
}

function RenderReportsTable() {
	var table = CreateTable('rptPrcTbl','reportsTbl');
	
	AddTableHeaderTextCell(table, 'Unhandled Report');
	AddTableHeaderTextCell(table, 'Reason');
	AddTableHeaderTextCell(table, 'Delete');	
	
	var tBody = table.tBodies[0];
	
	var reports = ReportProcessorData.unhandledReports;
	for(var i=0; i<reports.length; i++) {
		if(!reports[i].id) {
			AmendReport(reports[i]);
			SaveReportProcData();
		}
		var row = document.createElement('tr');
		if(reports[i].id==GetQueryStringValue('id')) {
			row.className = 'currentReport';
		}
		tBody.appendChild(row);
		
		var td = document.createElement('td');
		td.appendChild(CreateLink(reports[i].link, reports[i].title));
		row.appendChild(td);
		
		row.appendChild(CreateTableCell(reports[i].log));
		
		var checkbox = document.createElement('input');
		checkbox.type = "checkbox";
		checkbox.name = "rpt_"+i;
		checkbox.value = reports[i].id;
		checkbox.id = "rpt_"+i;
		checkbox.addEventListener("change", RemoveReport, true);
		
		var td = document.createElement('td');
		td.appendChild(checkbox);
		row.appendChild(td);
	}
	
	insertAfter(document.getElementById('side_info').lastChild, table);
}

function RenderAddAsFarmLink() {
	var farmId = GetQueryStringValue('d');
	if(farmId) {
		var a = document.createElement('a');
		a.href = 'javascript: ;';
		if(IsFarm(farmId)) {
			a.appendChild(document.createTextNode('» Remove from farm list'));
			a.addEventListener("click", RemoveFarmAndRefresh, true);
		}
		else {
			a.appendChild(document.createTextNode('» Add as farm'));
			a.addEventListener("click", AddFarmFromKartePage, true);
		}
		var tr = document.createElement('tr');	
		var td = document.createElement('td');
		td.appendChild(a);
		tr.appendChild(td);
		
		var optionsTable = document.getElementById('options');
		if(optionsTable) {
			optionsTable.tBodies[0].appendChild(tr);
		}
	}
}

function RenderProcessReportLink() {
	var p = document.createElement('p');
	p.className = "trptprc_resendContainer";	
	
	var a1 = document.createElement('a');
	a1.href = 'javascript: ;';
	a1.appendChild(document.createTextNode('More (+'+ReportProcessorData.incRatio+'%)'));
	a1.addEventListener("click", ResendMore, true);	
	
	var a2 = document.createElement('a');
	a2.href = 'javascript: ;';
	a2.appendChild(document.createTextNode('Same (+0)'));
	a2.addEventListener("click", ResendSame, true);	 
	
	var a3 = document.createElement('a');
	a3.href = 'javascript: ;';
	a3.appendChild(document.createTextNode('Less (-'+ReportProcessorData.decRatio+'%)'));
	a3.addEventListener("click", ResendLess, true);	
	
	var b = document.createElement('b');	
	var villageId = GetFarmIdFromReportPage();
	if(IsFarm(villageId)) {
		b.appendChild(document.createTextNode('Resend troops'));
	}
	else {
		b.appendChild(document.createTextNode('Resend troops and add as farm'));
	}
	
	p.appendChild(b);
	p.appendChild(a1);
	p.appendChild(a2);
	p.appendChild(a3);
	
	insertAfter(document.getElementById('textmenu'), p); 
	
	
	// optimal farming sender	
	insertAfter(p, CreateSenderHint(villageId)); 
	

	// save report link
	var a4 = document.createElement('a');
	a4.href = 'javascript: ;';
	a4.appendChild(document.createTextNode('Add to unhandled reports'));
	a4.addEventListener("click", AddToUnhandled, true);
	insertAfter(p, a4); 
}

function CreateSenderHint(farmId) {
	var raceNo = parseInt(ReportProcessorData.race);
	var senderId = GetSenderIdFromReportPage();
	var lastSender = GetVillage(senderId);
	var lastSenderTroopType = 1;
	var xy = id2xy(farmId);
	var farmX = xy[0];
	var	farmY = xy[1];
	var lastDistance = getDistance(lastSender.x, lastSender.y, farmX, farmY);
	var tournamentLevel = lastSender.tournamentSquareLevel;
		
	// find out which troop was used last time	
	var lastSenderTroopType;
	var attCells = document.getElementById('attacker').rows[2].cells;
	for(var v=1; v<10; v++) {
		attacking = attCells[v].textContent;		
		if(attacking && attacking!=0) {		
			lastSenderTroopType = v;
			break;
		}
	}
	
	var lastTravelTime = getTravelTime(lastSenderTroopType, raceNo, lastDistance, tournamentLevel);
	
	// create the table
	var table = CreateTable('rptOptTbl','optimalTbl');
	AddTableHeaderTextCell(table, 'Sender');
	for(var x=1; x<7; x++) {
		AddTableHeaderCell(table, CreateImage("img/x.gif", 'unit u' + raceNo + x));
	}
	var tBody = table.tBodies[0];
	
	
	for(var i=0; i<villages.length; i++) {
		if(!villages[i].showAsSender)
			continue;
			
		var distance = getDistance(villages[i].x, villages[i].y, farmX, farmY);
		
		var row = document.createElement('tr');
		tBody.appendChild(row);
		
		var td = document.createElement('td');
		td.appendChild(document.createTextNode(villages[i].name));
		row.appendChild(td);
		
		tournamentLevel = villages[i].tournamentSquareLevel;
		
		for(var n=0; n<6; n++) {
			var tt = getTravelTime(n+1, raceNo, distance, tournamentLevel);
			var td = document.createElement('td');
			
			var diff = lastTravelTime / tt;
			
			var className = "same";
			if(diff > 2)
				className = "radical";
			else
				if(diff > 1.5)
					className = "super";
				else
					if(diff > 1.1)
						className = "better";
					else
						if(diff < 0.7)
							className = "worst";
						else
							if(diff < 0.9)
								className = "worse";
			td.className = className;
			
			if(villages[i].id == senderId && lastSenderTroopType == n+1)
				td.className += ' activeVillageTd';
			td.appendChild(document.createTextNode(formatTime(tt, 0)));
			row.appendChild(td);
		}
	}
	
	// a final row with a link	
	var customLink = document.createElement('a');
	customLink.href = 'javascript: ;';
	customLink.appendChild(document.createTextNode('Configure optimization hints table'));
	customLink.addEventListener("click", ShowSenderSetup, true);
	
	var row = document.createElement('tr');
	tBody.appendChild(row);
	
	var th = document.createElement('th');
	th.setAttribute('colspan', '7');
	th.appendChild(customLink);
	th.className = 'lastRow';
	row.appendChild(th);

	return table;
}


function RenderFakeLinks() {
	// render some instructions and settings
	var p = document.createElement('p');
	p.className = "trptprc_fakesContainer";	
	
	var intro = document.createElement('p');	
	intro.appendChild(document.createTextNode('Clicking the "send fakes" image below will send with the following settings. A good advice is to CTRL+click the image. This will open a new tab in your browser where the fake will be sent.'));
	
	var radioDesc = document.createElement('p');
	radioDesc.appendChild(document.createTextNode('Troop type to send as fake: '));
	
	var radioContainer = document.createElement('div');
	radioContainer.className = "radioContainer";
	for(var t=1; t<9; t++) {
		var radio = document.createElement('input');
		radio.type = 'radio';
		radio.name = "fakeTroopType";
		radio.id = "fakeTroopType";
		radio.value = t;
		if(ReportProcessorData.fakeTroopType==t) {
			radio.setAttribute('checked', 'true');
		}
		radio.groupName = 'fakeTroopType';
		radio.addEventListener("click", SetFakeTroopType, true);
				
		// troop type image		
		var td = document.createElement('td');
		var img = document.createElement('img')
		img.src = "img/x.gif";
		img.className = 'unit u' + raceImageNumber + t;
		
		radioContainer.appendChild(img);		
		radioContainer.appendChild(radio);
	}
	
	p.appendChild(intro);	
	p.appendChild(radioDesc);
	p.appendChild(radioContainer);
	
	insertAfter(document.getElementById('profile'), p); 
	
	// add send fake links to the village list
	var villageTable = document.getElementById('villages');
	var rows = villageTable.tBodies[0].rows;
	for(var r=0; r<rows.length; r++) {
		var villageUrl = xpathToFirstFound("a", rows[r].cells[0]).href;
		var villageId = GetQueryStringValue('d', ParseQueryString(villageUrl.substring(villageUrl.indexOf('?')+1)))
		
		var img = GetImage('bandit');
		img.title = "Send fake attack/raid";
		var a = document.createElement('a');
		a.href = 'a2b.php?z='+villageId;
		a.setAttribute('villageid', villageId);
		a.appendChild(img);
		a.addEventListener("click", SendFake, true);	
		var td = rows[r].cells[0].appendChild(a);
	}
}

/* ===================================== DATA OBJECT ======================================= */


function LoadReportProcData() {
	var valueName = GetServerName()+GetUserId()+'ReportProcessorData'
	// legacy check
	if(!isChrome && !GM_getValue(valueName)) {
		ReportProcessorData = eval(GM_getValue('ReportProcessorData','new Object()'));
	}
	else {
		if(isChrome) {	
			ReportProcessorData = eval(readCookie(valueName,'new Object()'));
		}
		else {
			ReportProcessorData = eval(GM_getValue(valueName,'new Object()'));
		}
	}
	
	if(!ReportProcessorData || !ReportProcessorData.farms){
		ReportProcessorData = new Object();
		ReportProcessorData.farms = new Array();
		ReportProcessorData.unhandledReports = new Array();
		ReportProcessorData.activated = false;
		ReportProcessorData.race = '1';
		ReportProcessorData.minRaiders = 12;
		ReportProcessorData.incRatio = 50;
		ReportProcessorData.decRatio = 20;
		ReportProcessorData.lossAlertPercentage = 50;
		ReportProcessorData.returnToReports = false;
	}
}
function SaveReportProcData() {
	var valueName = GetServerName()+GetUserId()+'ReportProcessorData'
	
	if(isChrome) {
		var jsonString = CustomUneval(ReportProcessorData);
		createCookie(valueName, jsonString, 365);
	}
	else {
		var jsonString = uneval(ReportProcessorData)
		GM_setValue(valueName, jsonString);
	}
}

function ClearData() {
	if(confirm('Do you really wish to delete all farms?')) {
		ReportProcessorData = new Object();
		ReportProcessorData.farms = new Array();
		ReportProcessorData.unhandledReports = new Array();
		ReportProcessorData.activated = false;
		ReportProcessorData.race = '1';
		ReportProcessorData.minRaiders = 12;
		ReportProcessorData.incRatio = 50;
		ReportProcessorData.decRatio = 20;
		ReportProcessorData.lossAlertPercentage = 50;
		ReportProcessorData.returnToReports = false;
		SaveReportProcData();
		
		document.location.reload();
	}
}

// Manually builds a json string out of the ReportProcessorData object
// remember to modify this if you add/change the reportProcessorData object.
// this is for Chrome only since they don't have uneval()
function CustomUneval(procObj) {
	var data = new Array();
	
	// begin object
	data[0] = '({';
	
	// farms
	data[1] = 'farms:[';
	for(var i=0; i<ReportProcessorData.farms.length; i++) {
		if(i>0)
			data[data.length] = ', '
		data[data.length] = Farm2json(ReportProcessorData.farms[i]);
	}
	data[data.length] = '] ';

	// myVillages	
	if(ReportProcessorData.myVillages) {
		data[data.length] = ', myVillages:[';
		for(var i=0; i<ReportProcessorData.myVillages.length; i++) {
			if(i>0)
				data[data.length] = ', '
			data[data.length] = '"' + ReportProcessorData.myVillages[i] + '"';
		}
		data[data.length] = '] ';
	}

	// fakeTargetVillages	
	if(ReportProcessorData.fakeTargetVillages) {
		data[data.length] = ', fakeTargetVillages:[';
		for(var i=0; i<ReportProcessorData.fakeTargetVillages.length; i++) {
			if(i>0)
				data[data.length] = ', '
			data[data.length] = '"' + ReportProcessorData.fakeTargetVillages[i] + '"';
		}
		data[data.length] = '] ';
	}
	
	// UnhandledReports
	if(ReportProcessorData.UnhandledReports) {
		data[1] = 'UnhandledReports:[';
		for(var i=0; i<ReportProcessorData.UnhandledReports.length; i++) {
			var rpt = ReportProcessorData.UnhandledReports[i];
			
			if(i>0)
				data[data.length] = ', '
			data[data.length] = '{link:"' + rpt.link + '", title:"' + rpt.title + '"}';
		}
		data[data.length] = '] ';
	}
	
	// farmInProcess
	data[data.length] = ', farmInProcess=' + Farm2json(ReportProcessorData.farmInProcess);
	
	// reportInProcess
	if(ReportProcessorData.reportInProcess) {
		data[data.length] = ', reportInProcess={link:"' + ReportProcessorData.reportInProcess.link + ', title:"' + ReportProcessorData.reportInProcess.title + ', log:"' + ReportProcessorData.reportInProcess.log + ', id:"' + ReportProcessorData.reportInProcess.id + '}';
	}
	else {
		data[data.length] = ', reportInProcess=null';
	}
	
	// props	
	data[data.length] = ', activated=' + ((ReportProcessorData.activated) ? "true" : "false");
	data[data.length] = ', returnToReports=' + ((ReportProcessorData.returnToReports) ? "true" : "false");
	if(ReportProcessorData.lastReportPageNumber != null)
		data[data.length] = ', lastReportPageNumber=' + ReportProcessorData.lastReportPageNumber;	
	if(ReportProcessorData.lastReportLinkFollowed != null)
		data[data.length] = ', lastReportLinkFollowed="' + ReportProcessorData.lastReportLinkFollowed + '"';
	data[data.length] = ', race="' + ReportProcessorData.race + '"';
	data[data.length] = ', minRaiders="' + ReportProcessorData.minRaiders + '"';
	data[data.length] = ', incRatio="' + ReportProcessorData.incRatio + '"';
	data[data.length] = ', decRatio="' + ReportProcessorData.decRatio + '"';
	data[data.length] = ', lossAlertPercentage="' + ReportProcessorData.lossAlertPercentage + '"';
	
	
	if(ReportProcessorData.fakeTroopType != null)
		data[data.length] = ', fakeTroopType="' + ReportProcessorData.fakeTroopType + '"';
	
	// close the data object
	data[data.length] = '})';
	
	return data.join('');
}

function Farm2json(farm) {
	if(!farm) {
		return "null";
	}
	return '{villageId:"' + farm.villageId + '", villageLink:"' + farm.villageLink + '", villageName:"' + farm.villageName + '", playerId:"' + farm.playerId + '", autoAdjustEnabled:' + ((farm.autoAdjustEnabled)?'true':'false') + ', troopType:' + farm.troopType + ', troopNumber:' + farm.troopNumber + ', senderVillageId:"' + farm.senderVillageId + '", attackedCount:' + farm.attackedCount + ', averageBounty:' + farm.averageBounty + ', farmUrl:"' + farm.farmUrl + '"}';
}

/* ================================ ADD / REMOVE FARM ===================================== */

function AddFarmFromKartePage() {
	var farm = CreateFarmFromKartePage();
	AddFarm(farm);
}

function RemoveFarmAndRefresh() {	
	LoadReportProcData(); // ensure that we get the latest data possible	
	var villageId = GetQueryStringValue('d');	
	var result = RemoveFarm(villageId);	
	SaveReportProcData();	
	if(result) {
		document.location.href = crtPage;
	}
}

function AddFarm(farm) {
	LoadReportProcData(); // ensure that we get the latest data possible
	
	if(IsFarm) {
		document.location.href = crtPage;
	}	
	
	var existingFarms = ReportProcessorData.farms;		
	existingFarms[existingFarms.length] = farm;
	
	ReportProcessorData.farms = existingFarms;
	SaveReportProcData();
	
	document.location.href = crtPage;
}

function RemoveFarm(villageId) {
	var farms = ReportProcessorData.farms;
	var idx = -1;
	for(var i = 0; i<farms.length; i++) {
		if(farms[i].villageId == villageId) {
			idx = i;
			break;
		}
	}
	
	if(idx > -1) {
		ReportProcessorData.farms.splice(idx, 1);
		return true;
	}
	return false;
}

function GetSingleFarm(villageId) { 
	var farms = ReportProcessorData.farms;
	for(var i=0; i<farms.length; i++) {
		if(farms[i].villageId == villageId) {
			return farms[i];
		}
	}
	return new Farm(villageId, "", "", "", "", true, 1, 12, activeVillage.id);  // TODO this seems wrong
}

function Farm(villageId, villageLink, villageName, playerId, playerName, autoAdjustEnabled, troopType, troopNumber, senderVillageId) {
	this.villageId = villageId;
	this.villageLink = villageLink;
	this.villageName = villageName;
	this.playerId = playerId;
	this.playerName = playerName;
	this.autoAdjustEnabled = autoAdjustEnabled;
	this.troopType = troopType;
	this.troopNumber = troopNumber;
	this.senderVillageId = senderVillageId;
	this.attackedCount = 0;
	this.averageBounty = 0;
	this.attackType = 2; // 1=normal, 2=raid
}

function IsFarm(villageId) {
	var farms = ReportProcessorData.farms;
	for(var i=0; i<farms.length; i++) {
		if(farms[i].villageId == villageId)
			return true;
	}
	return false;
}

function CreateFarmFromKartePage() {
	var villageInfoTable = document.getElementById('village_info');
	
	var villageLink = crtPage;
	var villageId = GetQueryStringValue('d');
	var villageName = villageInfoTable.rows[0].cells[0].textContent;
	villageName = villageName.substring(0, villageName.lastIndexOf('(')-1);
	
	var playerLink = villageInfoTable.rows[3].cells[1].childNodes[0];
	var playerHref = playerLink.href;
	
	var playerId = playerHref.substring(playerHref.lastIndexOf('uid=')+4);
	var playerName = playerLink.textContent;
	var autoAdjustEnabled = true;
	var troopType = defaultTroopType;
	var troopNumber = defaultTroopNumber;
	var senderVillageId = activeVillage.id;
	
	return new Farm(villageId, villageLink, villageName, playerId, playerName, autoAdjustEnabled, troopType, troopNumber, senderVillageId);
}

// Checks if the currently displayed village is a farm and if so updates the name and player data
function UpdateFarmDataFromKartePage() {
	var villageInfoTable = document.getElementById('village_info');
	
	var villageLink = crtPage;
	var villageId = GetQueryStringValue('d');
	
	LoadReportProcData(); // ensure that we get the latest data possible
	if(IsFarm(villageId)) {
		if (villageInfoTable== null) {
			RemoveFarm(villageId);
		}
		else {
			var farm = GetSingleFarm(villageId);
					
			var villageName = villageInfoTable.rows[0].cells[0].textContent;
			farm.name = villageName.substring(0, villageName.lastIndexOf('(')-1);
			
			var playerLink = villageInfoTable.rows[3].cells[1].childNodes[0];
			var playerHref = playerLink.href;	
			farm.playerId = playerHref.substring(playerHref.lastIndexOf('uid=')+4);
			farm.playerName = playerLink.textContent;
			farm.villageLink = villageLink;
			
			UpdateFarm(farm);
		}
	}
	
	SaveReportProcData();
}


function UpdateFarmDataFromReport(farm) {	
	var defTd = xpathToFirstFound("//table[@class='defender']").rows[0].cells[1];
	var attTd = document.getElementById('attacker').rows[0].cells[1];
	
	var playerName = defTd.childNodes[0].textContent;
	var playerLink = defTd.childNodes[0].href;
	
	var villageLink = xpathToFirstFound("a[contains(@href, 'karte.php')]", defTd).href;
	var farmName = xpathToFirstFound("a[contains(@href, 'karte.php')]", defTd).textContent;
	var senderVillageHref = xpathToFirstFound("a[contains(@href, 'karte.php')]", attTd).href;
	
	farm.villageLink = villageLink;
	farm.villageName = farmName;
	farm.playerId = GetQueryStringValue('uid', ParseQueryString(playerLink.substring(playerLink.indexOf('?')+1)));
	farm.playerName = playerName;
	farm.senderVillageId = GetQueryStringValue('d', ParseQueryString(senderVillageHref.substring(senderVillageHref.indexOf('?')+1)));
	
	// fix the village list
	if(activeVillage == null) {
		FixVillageList(senderVillageHref.textContent, senderVillageId);
	}
	
	DebugAlert('updated farm with villageLink='+villageLink+', villageName='+farmName+', senderVillageId='+farm.senderVillageId+', playerName='+playerName+', playerId='+farm.playerId)
	
	return farm;
}

function UpdateFarm(farm, skipLoad) {	
	if(!skipLoad) {
		LoadReportProcData(); // ensure that we get the latest data possible
	}
	var farms = ReportProcessorData.farms;
	for(var i=0; i<farms.length; i++) {
		if(farms[i].villageId == farm.villageId)  {
			ReportProcessorData.farms[i] = farm;
			SaveReportProcData();
			return;
		}
	}
	
	// if we didn't find it we add it
	AddFarm(farm);
	SaveReportProcData();
}

function ToggleAutoAdjust(e) {
	var cbx;
	if (!e) var e = window.event;
	if (e.target) cbx = e.target;
	else if (e.srcElement) cbx = e.srcElement;
	if (cbx.nodeType == 3) // defeat Safari bug
		cbx = cbx.parentNode;
	
	var villageId = cbx.value;
	var autoAdjustEnabled = cbx.checked;
	
	var farm = GetSingleFarm(villageId);
	farm.autoAdjustEnabled = autoAdjustEnabled;
	
	UpdateFarm(farm, true);
}

function ToggleAttackType(e) {
	var cbx;
	if (!e) var e = window.event;
	if (e.target) cbx = e.target;
	else if (e.srcElement) cbx = e.srcElement;
	if (cbx.nodeType == 3) // defeat Safari bug
		cbx = cbx.parentNode;
	
	var villageId = cbx.value;
	var attackType = (cbx.checked) ? 2 : 1;
	
	var farm = GetSingleFarm(villageId);
	farm.attackType = attackType;
	
	UpdateFarm(farm, true);
}

/* ===================================== REPORT PROCESSING ======================================= */


function StartProcessing() {
	DebugAlert('Start processing reports!');
	LoadReportProcData(); // ensure that we get the latest data possible
	ReportProcessorData.activated = true;
	ReportProcessorData.lastReportLinkFollowed = null;
	SaveReportProcData();
	document.location.href = 'berichte.php?t=3';
}

function StopProcess() {
	LoadReportProcData(); // ensure that we get the latest data possible
	ReportProcessorData.activated = false;
	ReportProcessorData.lastReportLinkFollowed = null;
	SaveReportProcData();
	DebugAlert('Completed processing reports!');
	document.location.href = 'berichte.php';
}

function ProcessReportList() {
	LoadReportProcData(); // ensure that we get the latest data possible
	if(!ReportProcessorData.activated) {
		StopProcess();
		return;
	}

	var rptTable = document.getElementById('overview');
	
	// get the previous and next links 
	var previousUrl;
	var nextUrl;
	var lastCell = rptTable.rows[rptTable.rows.length-1].cells[2];
	if(lastCell.childNodes.length > 1) {
		var previousUrl = lastCell.childNodes[0].href;
		var nextUrl = lastCell.childNodes[1].href;
	}
	
	var lastNewReportUrl;
	var a;
	var newAttackCount = 0;
	var foundLastReportFollowed = false;
	
	DebugAlert('lastReportLinkFollowed:'+ReportProcessorData.lastReportLinkFollowed);
	
	
	// parse all rows and gather some intel
    var rows = document.getElementById("overview").rows;
    for(var i=1; i<rows.length-1; i++) {
		var td = rows[i].cells[1];		
		
		if(!td) {
			continue;
		}
		
		//check if it is a new report
		var isNew = false;
		var div = xpathToFirstFound("div", td);
		for(var c=0; c<div.childNodes.length; c++) {
			var node = div.childNodes[c];
			if(!node.tagName && node.textContent.length > 2)
				isNew = true;
		}
		
		// try to determine if the report is unread
		/*
		var newIndicator = "";
		
		if(BeyondActivated) { // using travian beyond
			newIndicator = td.childNodes[2].childNodes[2].textContent;
		}
		else {
			newIndicator = td.childNodes[2].childNodes[1].textContent;
		}
		var isNew = newIndicator.indexOf("("+phrases["NEW"]+")") > -1;
		
		// handle the mysteries of double byte characters
		if(phrases["NEW"].length == 1 && newIndicator.substring(1).charCodeAt(0) == phrases["NEW"].charCodeAt(0)) {
			isNew = true;
		}
		*/
		a = xpathToFirstFound("div/a[contains(@href, 'berichte.php')]", td);
		
		// check if we find the current report list page contains the report last handled
		if(ReportProcessorData.lastReportLinkFollowed != null && a.href.toLowerCase().indexOf(ReportProcessorData.lastReportLinkFollowed.toLowerCase()) > -1){
			DebugAlert('Found last followed report!');
			foundLastReportFollowed = true;
		}		
		
		if(isNew)
		{
			var img = xpathToFirstFound("img", td);
			var reportId = a.href.substring(a.href.lastIndexOf('id=')+3);
			
			/* attack, won w/o losses                           attack, won w losses    */
			if(img.className.indexOf('iReport1') > -1  ||  img.className.indexOf('iReport2') > -1) {
				newAttackCount++;
				lastNewReportUrl = a.href;
			}
		}
	}
	
	DebugAlert('Found '+newAttackCount+' new attacks last report url is:'+lastNewReportUrl+' and foundLastReportFollowed:'+foundLastReportFollowed);
	
	var lastReportPageNumber = ReportProcessorData.lastReportPageNumber; 
	var thisReportPageNumber = GetQueryStringValue('s') || 0;
	
	DebugAlert('Last page='+lastReportPageNumber+' This page='+thisReportPageNumber);
	
	// browse the report lists and find the (most likely) oldest attack with new-flag
	if(ReportProcessorData.lastReportPageNumber == null) {
		DebugAlert('lastReportPageNumber is null');
			
		if(!lastNewReportUrl) { // inga attacker med (ny)
			DebugAlert('no new attacks, stopping');
			StopProcess();
		}
		else {
			if(nextUrl && !foundLastReportFollowed) {
				DebugAlert('attacks found, checking next page...');
				ReportProcessorData.lastReportPageNumber = thisReportPageNumber
				SaveReportProcData();
				GoToPage(nextUrl, ReportProcessorData.delay); // make sure no reports are left behind
			}
			else {
				DebugAlert('attacks found, no next-page, going to report.');
				GoToPage(lastNewReportUrl, ReportProcessorData.delay);
			}
		}
	}
	else
	{
		DebugAlert('lastReportPageNumber is populated');
			
		if(lastNewReportUrl) // found at least 1 new attack report
		{
			// we came from a previous report list page	
			if(Number(lastReportPageNumber) <= Number(thisReportPageNumber) && nextUrl && !foundLastReportFollowed) {  
				DebugAlert('Going to next page... lastReportPageNumber:'+lastReportPageNumber+' thisReportPageNumber:'+thisReportPageNumber+' nextUrl:'+nextUrl);		
				SaveReportProcData(); 
				GoToPage(nextUrl, ReportProcessorData.delay); // make sure no reports are left behind
			}
			else {    // we have just visited the next report list page but didn't found any new reports so we went back here
				DebugAlert('Already visited the next page or no next page or found the previously handled report on this page, going to report ' + lastNewReportUrl);
				ReportProcessorData.lastReportPageNumber = null;
				SaveReportProcData();
				GoToPage(lastNewReportUrl, ReportProcessorData.delay);
			}
		}
		else {
			ReportProcessorData.lastReportPageNumber = thisReportPageNumber;
			SaveReportProcData();
			if(previousUrl) {
				DebugAlert('no attack erports found, going to previous page...');
				GoToPage(previousUrl, ReportProcessorData.delay);
			}
			else {
				DebugAlert('no attack reports found no previous page, stopping...');
				StopProcess();
			}
		}
	}
}

function GetFarmIdFromReportPage() {
	var farmLink = xpathToFirstFound("//table[@class='defender']//a[contains(@href, 'karte.php?d=')]");
	if(!farmLink) {
		return null;
	}
	var farmUrl = farmLink.href;
	return GetQueryStringValue('d', ParseQueryString(farmUrl.substring(farmUrl.indexOf('?')+1)));	
}
function GetSenderIdFromReportPage() {
	var attTd = document.getElementById('attacker').rows[0].cells[1];
	var senderVillageHref = xpathToFirstFound("a[contains(@href, 'karte.php')]", attTd).href;
	return GetQueryStringValue('d', ParseQueryString(senderVillageHref.substring(senderVillageHref.indexOf('?')+1)));;
}

function ResendMore() {
	HandleSingleReport((Number(ReportProcessorData.incRatio) + 100) / 100, true);
}

function ResendLess() {
	HandleSingleReport((100 - Number(ReportProcessorData.decRatio)) / 100, true);
}
function ResendSame() {
	HandleSingleReport(1, true);
}
function AddToUnhandled() {
	var reportLink = crtPage;
	var reportTitle = document.getElementById('report_surround').rows[0].cells[1].textContent;
	var currentReport = new Report(reportLink, reportTitle);
	currentReport.log = 'Saved';
	
	LoadReportProcData(); // ensure that we get the latest data possible
	AddUnhandledReport(currentReport);
	SaveReportProcData();
}
function HandleSingleReport(troopMultiplier, manualOverride) {	
	LoadReportProcData(); // ensure that we get the latest data possible
	
	var reportLink = crtPage;
	var reportTitle = document.getElementById('report_surround').rows[0].cells[1].textContent;
	var currentReport = new Report(reportLink, reportTitle);
	
	var farmId = GetFarmIdFromReportPage();
	if(!farmId) {
		DebugAlert('Farm no longer exists')
		if(ReportProcessorData.activated) {
			currentReport.log = "Farm no longer exists";
			if(AddUnhandledReport(currentReport)) {
				SaveReportProcData();
			}
			document.location.href = 'berichte.php?t=3';
		}
		else {
			alert('Farm no longer exists')
		}
		return;
	}
	
	
	ReportProcessorData.lastReportLinkFollowed = reportLink;
	SaveReportProcData();
	
	// if not a farm we shouldn't process it, or else sweeps might be handled as farming raids and everything goes down the toilet
	if(ReportProcessorData.activated && !IsFarm(farmId)) {
		DebugAlert('not a farm and in automated mode')
		currentReport.log = "Not a farm";
		if(AddUnhandledReport(currentReport)) {
			SaveReportProcData();
		}
		document.location.href = 'berichte.php?t=3';
		return;
	}
	DebugAlert('is a farm or will be added')
	
	var farm = GetSingleFarm(farmId);  // will return a new blank farm if not found
	farm = UpdateFarmDataFromReport(farm);
	
	var attackingTroopType, attacking, lost;
	var attCells = document.getElementById('attacker').rows[2].cells;
	var resultCells = document.getElementById('attacker').rows[3].cells;
	for(var i=1; i<10; i++) {
		attacking = attCells[i].textContent;
		lost = resultCells[i].textContent;
		
		if(attacking && attacking!=0) {		
			attackingTroopType = i;
			var lossRatio = 100 / (attacking / lost);
			if(ReportProcessorData.activated && lossRatio > Number(ReportProcessorData.lossAlertPercentage)) { 
				DebugAlert('lost more than '+ReportProcessorData.lossAlertPercentage+'% troops');
				currentReport.log = "Major loss";
				if(AddUnhandledReport(currentReport)) {
					SaveReportProcData();
				}
				document.location.href = 'berichte.php?t=3';
				return;
			}
			break;
		}
	}
	
	// check bounty and rectify the number of attackers
	var bountyBody;
	var bodies = document.getElementById('attacker').tBodies;
	for(var b=0; b<bodies.length; b++) {
		if(bodies[b].className=='goods') {
			bountyBody = bodies[b];
			break;
		}
	}
	
	var bountyNodes = bountyBody.rows[0].cells[1].childNodes;
	var bountyText = bountyNodes[bountyNodes.length-1].textContent;
	
	var bounty = Number(bountyText.split('/')[0]);
	var capacity = Number(bountyText.split('/')[1]);
	
	if(troopMultiplier==null) {
		troopMultiplier = 1;
		if(farm.autoAdjustEnabled) {
			if(bounty == capacity) {
				troopMultiplier = (Number(ReportProcessorData.incRatio) + 100) / 100;
				//troopMultiplier = 1.5;
			}
			else {
				if(bounty < capacity/4) {
					troopMultiplier = (100 - Number(ReportProcessorData.decRatio)) / 100;
					//troopMultiplier = 0.8;
				}
			}
			
			if(attacking<minTroop) {
				attacking = Number(ReportProcessorData.minRaiders);
			}
		}
	}
	attacking = Math.round(attacking * troopMultiplier);
	
	// update the farm attacker settings
	farm.troopNumber = attacking;
	farm.troopType = attackingTroopType;
	
	// update farming statistics: number of times farmed and average bounty
	var average = farm.averageBounty;
	var times = farm.attackedCount;
	farm.averageBounty = Math.round(((average * times) + bounty) / (times + 1));
	farm.attackedCount = times + 1;
	
	// save farm
	UpdateFarm(farm);
	
	// set the farm as "in process"
	ReportProcessorData.farmInProcess = farm;
	ReportProcessorData.reportInProcess = currentReport;
	
	
	
	// save all changes
	SaveReportProcData();
	
	// go the attack screen
	document.location.href = "a2b.php?z=" + farm.villageId;	
}

function AddUnhandledReport(report) {	
	if(!ReportProcessorData.unhandledReports){
		ReportProcessorData.unhandledReports = new Array();
	}
	DebugAlert('Adding unhandled report');
	
	// don't create doubles
	for(var i=0; i<ReportProcessorData.unhandledReports.length; i++) {
		if(ReportProcessorData.unhandledReports[i].id == report.id) {
			return false;
		}
	}
	
	ReportProcessorData.unhandledReports[ReportProcessorData.unhandledReports.length] = report;
	
	return true;
}

function RemoveReport(e) {
	var cbx;
	if (!e) var e = window.event;
	if (e.target) cbx = e.target;
	else if (e.srcElement) cbx = e.srcElement;
	if (cbx.nodeType == 3) // defeat Safari bug
		cbx = cbx.parentNode;
	
	var reportId = cbx.value;
	RemoveUnhandledReport(reportId);
	
	var row = cbx.parentNode.parentNode;
	row.parentNode.removeChild(row);
}

function RemoveUnhandledReport(id) {
	LoadReportProcData();
	
	var rpts = ReportProcessorData.unhandledReports;
	var idx = -1;
	for(var i = 0; i<rpts.length; i++) {
		if(rpts[i].id == id) {
			idx = i;
			break;
		}
	}
	
	if(idx > -1) {
		ReportProcessorData.unhandledReports.splice(idx, 1);
		SaveReportProcData();
	}	
}

// adds the id property a report
function AmendReport(report) {
	report.id = GetQueryStringValue('id', ParseQueryString(report.link.substring(report.link.indexOf('?')+1)));	
	if(report.log == null) {
		report.log = "";
	}
}

function Report(link, title, log) {
	this.link = link;
	this.title = title;
	this.log = (log)?log:"";
	this.id = GetQueryStringValue('id', ParseQueryString(link.substring(link.indexOf('?')+1)));
}


/* ================================== ATTACK ==================================== */


function HandleAttackPage()
{
	// get farm id
	var farmId = GetQueryStringValue('z');
		
	if(farmId == null) {
		DebugAlert('Failed to retrieve farm id!');
		StopProcess();
	}
	
	LoadReportProcData(); // ensure that we get the latest data possible
	
	if(ReportProcessorData.farmInProcess == null || ReportProcessorData.farmInProcess.villageId != farmId) {
		nothingToProcess = true;
		DebugAlert('not the farm in process. Checking for fake sending');
		
		var farm = GetFakeTarget(farmId);
		if(!farm) {
			return;
		}
	}
	else {
		var farm = GetSingleFarm(farmId);
		
		// make sure the right sender village is selected
		if(activeVillage.id != "" && activeVillage.id != farm.senderVillageId) {
			DebugAlert('wrong sender, changing...');
			var village = GetVillage(farm.senderVillageId);
			if(!village) {			
				SaveReportAndContinue("Sender N/A");
				if(ReportProcessorData.activated) {
					document.location.href = 'berichte.php?t=3';
				}
				else {
					alert('Sender village no longer exists. The report was added to the unhandled reports list.');
				}
				return;
			}
			DebugAlert('going to '+village.setUrl);
			document.location.href = village.setUrl;
			return;
		}
	}
	// select attack type
	var attackType = farm.attackType || 2;
	var radioValue = (attackType==2) ? 4 : 3;
	//document.getElementById('coords').rows[attackType].cells[0].childNodes[0].childNodes[0].click();
	xpathToFirstFound("//input[@type='radio' and @value='"+radioValue+"']", document.getElementById('coords')).click();
		
	// fill out the attack form
	var troopBox = document.getElementsByName('t'+farm.troopType)[0]; //document.getElementById('t' + farm.troopType)   for some reason this stopped working
	
	var troopMaxLink = xpathToFirstFound("a", troopBox.parentNode);
	if(!troopMaxLink) {
		availableTroops = 0;
	}
	else {
		var availableTroops = troopMaxLink.textContent;
		//var availableTroops = troopBox.parentNode.childNodes[5].textContent;	
		availableTroops = Number(availableTroops.substring(1, availableTroops.length-1));
	}
	if(availableTroops < Number(farm.troopNumber)) {
		SaveReportAndContinue('Troops N/A');
		if(ReportProcessorData.activated) {
			document.location.href = 'berichte.php?t=3';
		}
		else {
			alert('Troops N/A. Need '+farm.troopNumber+' of troop type '+farm.troopType+'. The report was added to the unhandled reports list.');
		}
		return;
	}
	troopBox.value = farm.troopNumber;
		
	DebugAlert('Posting form...')
		
	// Post the form
	ClickButtonDelayed('btn_ok', ReportProcessorData.delay);
}
function SaveReportAndContinue(logMsg) {
	if(ReportProcessorData.reportInProcess == null) {
		return;
	}
	LoadReportProcData(); // ensure that we get the latest data possible
	ReportProcessorData.reportInProcess.log = logMsg;
	AddUnhandledReport(ReportProcessorData.reportInProcess);
	ReportProcessorData.farmInProcess = null;
	ReportProcessorData.reportInProcess = null;
	SaveReportProcData();	
}

function SendAttack() {
	var tbl = document.getElementById('short_info');
	if(!tbl) {	
		// returning troops....
		return;
	}
	
	var farmUrl = tbl.rows[0].cells[1].childNodes[0].href;
	var farmId = GetQueryStringValue('d', ParseQueryString(farmUrl.substring(farmUrl.indexOf('?')+1)));
	var farm;
	LoadReportProcData(); // ensure that we get the latest data possible
	
	if(ReportProcessorData.farmInProcess == null) {
		// check fakes
		farm = GetFakeTarget(farmId);
		if(!farm) {
			return;
		}
		else {
			// clean up the fake target queue
			var idx = ReportProcessorData.fakeTargetVillages.indexOf(farmId);
			if(idx > -1) {
				ReportProcessorData.fakeTargetVillages.splice(idx, 1);
				SaveReportProcData();
			}
		}
	}	
	else {	
		if(ReportProcessorData.farmInProcess.villageId != farmId) {
			DebugAlert('not the farm in process '+ReportProcessorData.farmInProcess.villageId+' vs ' + farmId);
			return;
		}
		
		var farm = GetSingleFarm(farmId);
		
		// make sure the right sender village is selected
		if(activeVillage.id!="" && activeVillage.id != farm.senderVillageId) {
			alert('Wrong sender village, saving the report as unhandled and returning to report processing')
			
			ReportProcessorData.reportInProcess.log = 'Village changed';
			AddUnhandledReport(ReportProcessorData.reportInProcess);
			ReportProcessorData.reportInProcess = null;
			ReportProcessorData.farmInProcess = null;
			SaveReportProcData();
			
			document.location.href = 'berichte.php?t=3';
			
			// TODO
			// this might be solved by switching the village and somehow retaining the current target... 
			
			//var village = GetVillage(farm.senderVillageId);
			//document.location.href = village.setUrl;
			return;
		}
		
		ReportProcessorData.farmInProcess = null;
		ReportProcessorData.reportInProcess = null;
		ReportProcessorData.returnToReports = true;
		SaveReportProcData();
	}
	DebugAlert('Sending troops...')
	
	ClickButtonDelayed('btn_ok', ReportProcessorData.delay);
}

/* ================================= FAKES ======================================= */

function SendFake(e) {	
	var img;
	if (!e) var e = window.event;
	if (e.target) img = e.target;
	else if (e.srcElement) img = e.srcElement;
	if (img.nodeType == 3) // defeat Safari bug
		img = img.parentNode;
	
	var villageId = img.parentNode.getAttribute('villageid'); 
	
	LoadReportProcData(); // ensure that we get the latest data possible
	
	if(ReportProcessorData.fakeTargetVillages == null) {
		ReportProcessorData.fakeTargetVillages = new Array();
	}
	
	// check for dupes
	var targets = ReportProcessorData.fakeTargetVillages;
	for(var t=0; t<targets.length; t++) {
		if(targets[t] == villageId) {
			return false;
		}
	}
	ReportProcessorData.fakeTargetVillages[targets.length] = villageId;
	SaveReportProcData();
}

function SetFakeTroopType(e) {
	var radio;
	if (!e) var e = window.event;
	if (e.target) radio = e.target;
	else if (e.srcElement) radio = e.srcElement;
	if (radio.nodeType == 3) // defeat Safari bug
		radio = radio.parentNode;
	
	var fakeTroopType = radio.value;
	
	LoadReportProcData(); // ensure that we get the latest data possible
	ReportProcessorData.fakeTroopType = fakeTroopType;
	SaveReportProcData();
}

function GetFakeTarget(villageId) {
	var fakeTargets = ReportProcessorData.fakeTargetVillages;
	for(var f=0; f<fakeTargets.length; f++) {
		if(fakeTargets[f] == villageId) {				
			// create a dummy farm object
			var farm = new Object();
			farm.attackType = 1; //1=attack 2=raid
			farm.troopType = ReportProcessorData.fakeTroopType;
			farm.troopNumber = 1;
			return farm;
		}
	}
}

/* ================================= VILLAGE LIST ======================================= */

function LoadVillageList() {
	villages = new Array();
	
	var extraVillageData = ReportProcessorData.extraVillageData;
	
	var vTbl = document.getElementById('vlist');
	if(!vTbl) {
		activeVillage = new Village("", "", 0, 0, "", false);
		return villages;
	}
	
	for(var i=1; i<vTbl.rows.length; i++) {
		var row = vTbl.rows[i];
		
		var name = row.cells[1].textContent;
		var xy = row.cells[2].textContent;
		var xyArray = FilterString(xy, "-0123456789|").split('|');
		var x = xyArray[0];
		var y = xyArray[1];
		var setUrl = row.cells[1].childNodes[0].childNodes[0].href;
		//var setUrl = xpathToFirstFound(".//a", row).href; 
		var id = xy2id(x, y);
		
		var tMinus = 0;
		var showAsSender = false;
		var tournamentSquareLevel = 0;
		var etaCell = CreateTableCell(" ");
		
		// get ExtraVillageData
		var ExtraVillageData = GetExtraVillageDataForVillage(id, true);
		if(ExtraVillageData) {
			tMinus = ExtraVillageData.ETA;
			showAsSender = ExtraVillageData.showAsSender;
			tournamentSquareLevel = ExtraVillageData.tournamentSquareLevel;
			
			// append ETA info to the rendered village list
			var etaCell;
			if(tMinus) {
				var ETA = new Date(tMinus*1);
				if(ETA > ((new Date().getTime())))
				{
					ETA = ETA.toTimeString().substr(0, 8);
					etaCell = CreateTableCell(ETA);
				}
			}
		}
		etaCell.className = "eta";
		row.appendChild(etaCell);
		
		var village = new Village(name, id, x, y, setUrl, showAsSender, tMinus, tournamentSquareLevel);
		
		if(row.cells[0].className.indexOf('hl') > -1) {
			activeVillage = village;
		}
		villages[villages.length] = village;
	}	
}

function FixVillageList(name, id) {
	if( villages.length == 0) {
		var first = new Village(name, id, 0, 0, "");
		activeVillage = first;
		villages[0] = first;
	}
}

function GetVillage(id) {
	for(var i=0; i<villages.length; i++) {
		if(villages[i].id == id) {
			return villages[i];
		}
	}
}
function GetExtraVillageDataForVillage(villageId, noLoad) {
	if(!noLoad)
		LoadReportProcData();
	var extraVillageData = ReportProcessorData.extraVillageData;
	if(extraVillageData) {
		for(var r=0; r < extraVillageData.length; r++) {
			if(extraVillageData[r].villageId == villageId) {
				return extraVillageData[r];
			}
		}
	}
}

function UpdateExtraVillageData(villageId, propName, newValue) {	
	LoadReportProcData();
	
	DebugAlert('Setting '+propName+' in village '+villageId+' to '+newValue);
	
	var extraVillageData = ReportProcessorData.extraVillageData;
	var evdExists = false;
	if(extraVillageData) {
		for(var r=0; r < extraVillageData.length; r++) {
			if(extraVillageData[r].villageId == villageId) {
				eval('extraVillageData[r].'+propName+' = newValue');
				evdExists = true;
				break;
			}
		}
	}
	if(!evdExists) {
		if(!extraVillageData)
			extraVillageData = new Array();
		var evd = new ExtraVillageData(villageId);
		eval('evd.'+propName+' = newValue');
		extraVillageData[extraVillageData.length] = evd;
	}
	
	// update the current village list as well
	eval('GetVillage(villageId).'+propName+' = newValue');
	
	ReportProcessorData.extraVillageData = extraVillageData;
	
	SaveReportProcData();
}

function ResolveVillageName(id) {
	var village = GetVillage(id);
	if(village) {
		return village.name;
	}
	
	return '?';
}

function Village(name, id, x, y, setUrl, showAsSender, ETA, tournamentSquareLevel) {
	this.name = name;
	this.id = id;
	this.x = x;
	this.y = y;
	this.setUrl = setUrl;
	this.showAsSender = showAsSender;
	this.ETA = ETA;
	this.tournamentSquareLevel = tournamentSquareLevel;
}

function ExtraVillageData(villageId) {
	this.villageId = villageId;
	this.ETA = "";
	this.tournamentSquareLevel = 0;
	this.showAsSender = false;
}

/*===================================== GET ETA =================================================*/

function TrackETAs() {
	var incomingAttackETA = GetFirstETA();
	
	if(incomingAttackETA == activeVillage.ETA) {
		return;
	}
	
	UpdateExtraVillageData(activeVillage.id, 'ETA', incomingAttackETA);
}

/*
att1 incoming attack
att3 incoming oasis attack
def1 returning troops
att2 outgoing attack
*/

function GetFirstETA() {
	var villageAttack = GetTminus(1);
	var oasisAttack = GetTminus(3);
	var firstETA;
	
	if(villageAttack != null){
		if(oasisAttack != null && oasisAttack < villageAttack) {
			firstETA = oasisAttack;
		}
		else {
			firstETA = villageAttack;
		}
	}
	else{
		if(oasisAttack != null) {
			firstETA = oasisAttack;
		}
	}
	
	if(firstETA != null) {
		//return new Date((new Date()).getTime() + (firstETA*1000));
		return (new Date()).getTime() + (firstETA*1000);
	}
}

/*
attackType = 1 (attack)  3 (oasis attack)
in seconds
*/
function GetTminus(attackType) {
	var node = xpathToFirstFound(".//img[@class='att"+attackType+"']", document.getElementById('movements'));
	while(node != null && node.tagName.toUpperCase() != 'TR') {
		node = node.parentNode;
	}
	if(node != null) {
		var countdown = xpathToFirstFound(".//span[contains(@id, 'timer')]", node);
		if(countdown != null) {
			var bits = countdown.textContent.split(':');
			return (bits[0]*60*60 + bits[1]*60 + bits[2]*1);
		}
	}
}




/* ===================================== SENDER HINTS ================================================= */

function ShowSenderSetup() {	
	var table = CreateTable('rptPrcTbl','sendersTbl');
	
	AddTableHeaderTextCell(table, 'Village');
	AddTableHeaderTextCell(table, 'Tournament Sq.');
	AddTableHeaderTextCell(table, 'Show');
	
	var tBody = table.tBodies[0];
	
	for(var i=0; i<villages.length; i++) {
		var row = document.createElement('tr');
		tBody.appendChild(row);
		
		var td = document.createElement('td');
		td.appendChild(document.createTextNode(villages[i].name));
		row.appendChild(td);
		
		var td = document.createElement('td');		
		var select = document.createElement('select');
		select.name = "villageTS_"+i;
		select.id = "villageTS_"+i;
		select.setAttribute('villageId', villages[i].id);
		for(var t=0; t<21; t++) {
			select.options[t] = new Option(t, t, false, (villages[i].tournamentSquareLevel==t));
		}
		select.addEventListener("change", UpdateTSLevel, true);		
		td.appendChild(select);
		row.appendChild(td);
		
		var td = document.createElement('td');		
		var checkbox = document.createElement('input');
		checkbox.type = "checkbox";
		checkbox.name = "senderVillage_"+i;
		checkbox.value = villages[i].id;
		checkbox.id = "senderVillage_"+i;
		checkbox.checked = villages[i].showAsSender;
		checkbox.addEventListener("change", ToggleShowAsSender, true);		
		td.appendChild(checkbox);
		row.appendChild(td);
	}
	
	// a container
	senderSetupDialogElement = document.createElement('div');
	senderSetupDialogElement.id = "rptPrcSenderSetup";
	senderSetupDialogElement.className = "rptPrcDialog";
	
	// close button
	var btn = document.createElement("button");
	btn.textContent = "Close";
	btn.addEventListener("click", HideSenderSetup, true);
	senderSetupDialogElement.appendChild(btn);
	
	// instructions
	var p = document.createElement('p');
	p.appendChild(document.createTextNode('Select your farming villages'));
	
	senderSetupDialogElement.appendChild(p);
	
	senderSetupDialogElement.appendChild(table);
	
	insertAfter(document.getElementById('side_info').lastChild, senderSetupDialogElement);
}

function HideSenderSetup() {
	if (senderSetupDialogElement) {
		senderSetupDialogElement.parentNode.removeChild(senderSetupDialogElement);
	}
}

function ToggleShowAsSender(e) {
	var cbx;
	if (!e) var e = window.event;
	if (e.target) cbx = e.target;
	else if (e.srcElement) cbx = e.srcElement;
	if (cbx.nodeType == 3) // defeat Safari bug
		cbx = cbx.parentNode;
	
	var villageId = cbx.value;
	
	UpdateExtraVillageData(villageId, 'showAsSender', cbx.checked);
}

function UpdateTSLevel(e) {
	var select;
	if (!e) var e = window.event;
	if (e.target) select = e.target;
	else if (e.srcElement) select = e.srcElement;
	if (select.nodeType == 3) // defeat Safari bug
		select = select.parentNode;
	
	var villageId = select.getAttribute('villageId');
	var tournamentSquareLevel = select.options[select.selectedIndex].value;
	
	UpdateExtraVillageData(villageId, 'tournamentSquareLevel', tournamentSquareLevel);
}

/* ===================================== SETTINGS ================================================= */

function SaveSettings(e) {
	var inputElement;
	if (!e) var e = window.event;
	if (e.target) inputElement = e.target;
	else if (e.srcElement) inputElement = e.srcElement;
	if (inputElement.nodeType == 3) // defeat Safari bug
		inputElement = inputElement.parentNode;
	
	var inputValue;
	
	if(inputElement.options) {
		inputValue = inputElement.options[inputElement.selectedIndex].value;
	}
	else {
		inputValue = inputElement.value;
	}
	
	var valueName = inputElement.getAttribute('valueName');
	
	LoadReportProcData(); // ensure that we get the latest data possible
	eval("ReportProcessorData." + valueName + " = inputValue");
	SaveReportProcData();
}

function ShowExportDialog() {
	var box = ShowImportExportDialog();
	var userId = GetUserId();
	var serverName = GetServerName();
	
	box.value = GM_getValue(serverName+userId+'ReportProcessorData');	
}
function ShowImportDialog() {	
	var box = ShowImportExportDialog();
	
	var btn = document.createElement("button");
	btn.textContent = "Import";
	btn.addEventListener("click", DoImport, true);
	importExportDialogElement.appendChild(btn);
}
function ShowImportExportDialog() {
	HideFarmSettings();

	importExportDialogElement = document.createElement('div');
	importExportDialogElement.id = 'importExportDialogElement';
	
	var box = document.createElement('textarea');	
	importExportDialogElement.appendChild(box);
	
	// close button
	var btn = document.createElement("button");
	btn.textContent = "Close";
	btn.addEventListener("click", HideImportExportDialog, true);
	importExportDialogElement.appendChild(btn);
	
	insertAfter(document.getElementById('side_info').lastChild, importExportDialogElement);
	
	return box;
}
function DoImport(e) {
	var btn;
	if (!e) var e = window.event;
	if (e.target) btn = e.target;
	else if (e.srcElement) btn = e.srcElement;
	if (btn.nodeType == 3) // defeat Safari bug
		btn = btn.parentNode;
	
	// get the textarea
	var textArea = xpathToFirstFound("textarea", btn.parentNode);
	
	// save changes
	if(confirm('This will replace all your current farms')) {
		try {
			ReportProcessorData = eval(textArea.value, 'new Object()');
			SaveReportProcData();
			HideImportExportDialog();
			alert("Import Complete!");
		}
		catch(e) {
			alert(e.message);
		}
	}
}
function HideImportExportDialog() {
	if (importExportDialogElement) {
		importExportDialogElement.parentNode.removeChild(importExportDialogElement);
	}
}

/* ===================================== TOOLS ================================================= */

function GoToPage(url, delay) {
	if(delay && !isNaN(delay)) {
		setTimeout("document.location.href = '"+url+"';", delay*1000);
	}
	else {
		document.location.href = url;
	}
}
function ClickButtonDelayed(buttonId, delay) {
	if(delay && !isNaN(delay)) {
		setTimeout("document.getElementById('"+buttonId+"').click();", delay*1000);
	}
	else {
		document.getElementById(buttonId).click();
	}
}

function insertAfter(node, referenceNode) {node.parentNode.insertBefore(referenceNode, node.nextSibling);};//insert a referenceNode after a specified node

function ParseQueryString(qstring) {	
	var queryStringValuePairs = new Array();
	
	var valuePairs = qstring.split('&');
	
	for(var i = 0; i<valuePairs.length; i++) {
		var valuePair = valuePairs[i].split('=');
		queryStringValuePairs[queryStringValuePairs.length] = new ValuePair(valuePair[0], valuePair[1]);
	}
	return queryStringValuePairs;
}

function ValuePair(key, value) {
	this.key = key;
	this.value = value;
}

// locates a value in a parsed querystring. If no qstring is passed we check the global querystring array
function GetQueryStringValue(key, qstring) {
	if(!qstring) {
		qstring = queryStringValuePairs;
	}
	
	key = key.toLowerCase();
	
	for(var i=0; i<qstring.length; i++) {
		if(qstring[i].key.toLowerCase() == key) {
			return qstring[i].value;
		}
	}
	return null;
}

function FilterString(str, allowedChars) {
	var clean = "";
	for(var i=0; i<str.length; i++) {
		if(allowedChars.indexOf(str[i]) > -1) {
			clean += str[i];
		}
	}
	return clean;
}

function GetUserId() {
	var profileLink = xpathToFirstFound("//div[@id='side_navi']//a[contains(@href, 'spieler.php')]") + "";  
	
	if (profileLink) {
		return GetQueryStringValue('uid', ParseQueryString(profileLink.substring(profileLink.indexOf('?')+1)));
	}
	return;
}
function GetServerName() {
	var serverName = window.location.href;
	serverName = serverName.substring(serverName.indexOf('/')+2);
	serverName = serverName.substring(0, serverName.indexOf('/'));
	return serverName;
}
	
function xpathToList(query, startNode) {
	if (!startNode) startNode = document;
    return document.evaluate(query, startNode, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
}

function xpathToFirstFound(query, startNode) {
	if (!startNode) startNode = document;
    return document.evaluate(query, startNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}


// Convert XY to a cell/village id
function xy2id(x, y) {
	return (1 + (parseInt(x) + 400) + (801 * Math.abs(parseInt(y) - 400)));
}
// Convert villagedId to XY
function id2xy(villagedId) {
	var arrXY = new Array; 
	var ivid = parseInt(villagedId); 
	arrXY[0] = (ivid%801?(ivid%801)-401:400); 
	arrXY[1] = 400 - (ivid - 401 - arrXY[0]) / 801; 
	return arrXY;
}

// calculates the distance between 2 villages
function getDistance(sx1, sy1, sx2, sy2) {
	var x1 = parseInt(sx1); var y1 = parseInt(sy1); var x2 = parseInt(sx2); var y2 = parseInt(sy2);
	dX = Math.min(Math.abs(x2 - x1), Math.abs(801 - Math.abs(x2 - x1)));
	dY = Math.min(Math.abs(y2 - y1), Math.abs(801 - Math.abs(y2 - y1)));
	dist = Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2));
	return dist;
};

// troopType = troop type 1-11
// raceNumber =  parseInt(ReportProcessorData.race) 0, 1  or 2
// baseDistance = go figure
// tournamentLvl = leave empty or set to 0 if no tournament present
function getTravelTime(troopType, raceNumber, distance, tournamentLvl) {
	var raceAdd = (raceNumber*10);
	var speed = troopStats[raceAdd + troopType][1];
	
	var baseDistance = distance;
	var tournamentDistance = 0;
	var serverType = (isSpeedServer) ? 2 : 1;
	
	if(tournamentLvl != null && tournamentLvl > 0 && distance > 30) {
		tournamentDistance = distance - 30;
		baseDistance = 30;
	}
	
	return Math.round(baseDistance * 3600 / speed / serverType + tournamentDistance * 3600 / speed / serverType / (1 + tournamentLvl/10));
}

// load and speed
var troopStats = new Array();
//Romans
troopStats[1] = [50,6];//Legionnaire
troopStats[2] = [20,5];//Praetorian
troopStats[3] = [50,7];//Imperian
troopStats[4] = [0,16];//Equites legati
troopStats[5] = [100,14];//Equites imperatoris
troopStats[6] = [70,10];//Equites cesaris
//Teutons
troopStats[11] = [60,7];//Club swinger
troopStats[12] = [40,7];//Spearman
troopStats[13] = [50,6];//Axeman
troopStats[14] = [0,9];//Scout
troopStats[15] = [110,10];//Paladin
troopStats[16] = [80,9];//Teutonic knight
//Gauls
troopStats[21] = [35,7];//Phalanx
troopStats[22] = [45,6];//Swordsman
troopStats[23] = [0,17];//Pathfinder
troopStats[24] = [75,19];//Theutates thunder
troopStats[25] = [35,16];//Druidrider
troopStats[26] = [65,13];//Haeduan

function formatTime(sec, aFormat){
		//aFormat: 0 = h:mm:ss (h = 0->... can be more than 24); 1 = days, h:mm:ss; 2 = h:mm:ss (h = 0->23:59:59 = only time)
		if (sec > -1) {
			var h = Math.floor(sec/3600);
			var m = Math.floor(sec/60) % 60;
			var s = parseInt(sec % 60);
			var ht = "";
			switch (aFormat) {
				case 1: var d = Math.floor(h/24); h = h - d * 24; ht += d + ", "; break;
				case 2: h = h % 24; break;
			};
			ht += h + ":" + (m > 9 ? m: '0' + m) + ":" + (s > 9 ? s : '0' + s);
		} else ht = "0:00:0?";
		h = null; m = null; s = null; d = null;
		return ht;
	};
	

/* update script, inspired by Travian Beyond */
function AutoUpdate() {
	var scriptUrl = 'http://userscripts.org/scripts/source/65944.user.js'
	
	GM_xmlhttpRequest({
		method: 'GET',
		url: scriptUrl + '?source',
		onload: function(result) {
			if (result.status != 200)
				return;
			if (!result.responseText.match(/@version\s+([\d.]+)/))
				return;
			var latestVersion = RegExp.$1;
			if (latestVersion == scriptVersion) {
				alert('You already have the latest version installed!');
				return;
			} 
			else {
				if (latestVersion < scriptVersion) {
					alert('You have a later version than available. You must have been into the future! Who will win the Superball this year? Is everyone wearing silver tights in the future?');
					return;
				} 
				else {
					if (window.confirm('There is a new version available, would you like to update?')) {
						window.location.href = scriptUrl;
					}
				}
			}
		}
	});
};


// cookies are used when running script in Chrome
function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else {
		var expires = "";
	}
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name,defaultvalue) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') {
			c = c.substring(1,c.length);
		}
		if (c.indexOf(nameEQ) == 0) {
			return c.substring(nameEQ.length,c.length);
		}
	}
	return defaultvalue;
}


function CreateTable(className, id) {
	var table = document.createElement("TABLE"); 
	table.className = className;
	table.id = id;
	var tHead = document.createElement("THEAD");
	var tBody = document.createElement("TBODY");
	
	table.appendChild(tHead);
	table.appendChild(tBody);
	
	table.tHead.appendChild(document.createElement('tr'));
	
	return table;
}

function AddTableHeaderTextCell(table, cellContent) {
	return AddTableHeaderCell(table, document.createTextNode(cellContent));
}
function AddTableHeaderCell(table, cellContent) {
	var th = document.createElement('th')
	th.appendChild(cellContent);
	table.tHead.rows[0].appendChild(th);
	
	return table;
}
function CreateTableCell(cellContent) {
	var td = document.createElement('td');
	td.appendChild(document.createTextNode(cellContent));
	return td
}

function CreateLink(href, title) {
	var a = document.createElement('a')
	a.href = href;
	a.appendChild(document.createTextNode(title));
	
	return a;
}

function CreateInput(elementId, value, caption, eventType, eventHandler, valueName) {
	var txt = document.createElement('input');
	txt.name = elementId;
	txt.id = elementId;
	txt.value = value;
	txt.setAttribute('valueName', valueName);
	txt.addEventListener(eventType, eventHandler, true);
	
	var container = document.createElement('div');
	container.appendChild(document.createTextNode(caption + ': '));
	container.appendChild(txt);
	
	return container;
}
function CreateImage(imgUrl, className) {
	var img = document.createElement('img')
	img.src = imgUrl;
	if(className)
		img.className = className;
	return img;
}

function AmendFarmList() {
	DebugAlert('Updating Farm List')
		
	LoadReportProcData(); // ensure that we get the latest data possible
	
	var farms = ReportProcessorData.farms;
	for(var i=0; i<farms.length; i++) {
		farms[i].autoAdjustEnabled = farms[i].autoIncreaseEnabled;
		farms[i].autoIncreaseEnabled = null;
		if(farms[i].attackType == null) {
			farms[i].attackType = 2;
		}
	}
	
	SaveReportProcData();
}

function DebugAlert(msg) {
	if(debugAlerts)
		alert(msg);
}

/* ===================================== BIG TEXTS ================================================= */

function GetFarmHelpText() {

	var helpText = document.createElement('div');
	helpText.id = "farmSettingsHelp";

	var text = new Array();
	text[0] = 'These villages are marked as farms and when you click the "Start Process" button, only reports of attacks to these villages will be resent.\n\n'
	text[1] = 'Auto adjust : Enable this to have the number of attackers auto adjusted. If they came back from a raid with full bounty, their numbers will be increased with 50%. However, if they come back empty handed, their numbers will decrease with 20%.\n\n';
	text[1] = 'Raid : Disable this checkbox to run normal attack instead of raids.\n\n';
	text[2] = 'To remove a farm from the list, click the village name and use the link on the village page.\n\n';
	
	for( var t=0; t<text.length; t++) {
		var paragraph = document.createElement('p');
		paragraph.appendChild(document.createTextNode(text[t]));
		helpText.appendChild(paragraph);
	}
	
    return helpText;
}


/* ===================================== IMAGES ================================================= */


function GetImage(imageName) {
	var img_src;
	switch (imageName) {
		case 'bandit':
			img_src = 'data:image/gif;base64,' +
				'R0lGODlhDwAPAPcAAAsLCw0NDRISEhQUFBUVFRYWFhoaGiAeFScjFyEhISIiIicnJygoKCsrKzExMTIy' +
				'MkdFPnFeH29fLWBUMHNfIXpnKHxpK39rKn9rLX1sNk5OTlJSUltYUVxcXHJsV350U2JiYnp6eo94MJN8' +
				'MYZ8XYF6ZK2ROa6SObKVN4GAf4qHf7Gic7aoesekNsGhOc6rPNGtONKuOtm0P+O7Oue9OfLGO/7RQf7Z' +
				'Yv7aaYGBgYODg4SEhIqKip6dl5mZmaGhoaenp6ysrLm0qLCwsLOzs729vcTEwsTExMXFxcnJyc7OztLQ' +
				'ytDQ0N7e3v723uDg4OXl5e7u7u/v7/767/Hx8fT09PX19fj4+P7+/v///wAAAAAAAAAAAAAAAAAAAAAA' +
				'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
				'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
				'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
				'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
				'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
				'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
				'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
				'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
				'ACwAAAAADwAPAAAIyQCzCJRCBMQDAA86AIkisCGUHQMMKACgwMCAHVAaXtHxIIBEigYCOAhhRWASBww8' +
				'TqwYYEGDI1iq8BCwQCXIlgJyUHmygaZNlgsEaGjCZAECEShYCFkhhAUKEQgSKClSYESNFxCMcEgxBUeN' +
				'EQSK/CBggYYMD0tK9HByg4YFAj/GHpBwgYSKDypIXJBwAO5Ynx+BCvBLQMCJGjNiwIgxo4aJwT+CFG5h' +
				'w0WGyy5stBg8BEnhCRQqYIiAoQKFCYOT/K0ZOGRQAj4CAgA7';
			break;
		default:
			return null;
	}
	var img_node = document.createElement('img');
	img_node.src = img_src;
	return img_node;
}



/* ===================================== STARTUP ================================================= */

// only works in FF, calling functionmain directly works in both Chrome and FF
if(isChrome) {
	functionMain();
}
else {
	window.addEventListener('load', function(e){ functionMain(e); }, false);
}